import * as path from 'path';

export class PathUtil {
  /**
   * 标准化路径，将所有反斜杠转换为正斜杠
   * @param p 需要标准化的路径
   * @returns 标准化后的路径
   */
  static normalize(p: string): string {
    return path.normalize(p).replace(/\\/g, '/');
  }

  /**
   * 比较两个路径是否相等，忽略路径分隔符差异
   * @param path1 第一个路径
   * @param path2 第二个路径
   * @returns 两个路径是否相等
   */
  static equals(path1: string, path2: string): boolean {
    try {
      const normalized1 = PathUtil.normalize(path1);
      const normalized2 = PathUtil.normalize(path2);

      // 移除末尾的斜杠再比较
      return normalized1.replace(/\/+$/, '') === normalized2.replace(/\/+$/, '');
    } catch (error) {
      console.error('路径比较错误:', error);
      return false;
    }
  }

  /**
   * 连接两个或多个路径段
   * @param paths 需要连接的路径段
   * @returns 连接后的路径
   */
  static join(...paths: string[]): string {
    try {
      // 使用 Node.js 的 path.join 然后标准化
      return PathUtil.normalize(path.join(...paths));
    } catch (error) {
      console.error('路径连接错误:', error);
      return '';
    }
  }

  /**
   * 提取路径的目录部分
   * @param p 输入路径
   * @returns 目录部分
   */
  static dirname(p: string): string {
    try {
      return PathUtil.normalize(path.dirname(p));
    } catch (error) {
      console.error('提取目录错误:', error);
      return '.';
    }
  }

  /**
   * 提取路径的文件名部分
   * @param p 输入路径
   * @returns 文件名部分
   */
  static basename(p: string): string {
    try {
      return path.basename(p);
    } catch (error) {
      console.error('提取文件名错误:', error);
      return '';
    }
  }

  /**
   * 判断路径是否为绝对路径
   * @param p 需要判断的路径
   * @returns 是否为绝对路径
   */
  static isAbsolute(p: string): boolean {
    try {
      return path.isAbsolute(p);
    } catch (error) {
      console.error('判断绝对路径错误:', error);
      return false;
    }
  }

  /**
   * 获取相对路径
   * @param from 起始路径
   * @param to 目标路径
   * @returns 从起始路径到目标路径的相对路径
   */
  static relative(from: string, to: string): string {
    try {
      return PathUtil.normalize(path.relative(from, to));
    } catch (error) {
      console.error('计算相对路径错误:', error);
      return '';
    }
  }

  /**
   * 解析路径
   * @param p 需要解析的路径
   * @returns 解析后的路径对象
   */
  static parse(p: string): path.ParsedPath {
    try {
      return path.parse(p);
    } catch (error) {
      console.error('解析路径错误:', error);
      return path.parse('');
    }
  }

  /**
   * 解析绝对路径
   * @param p 相对路径
   * @param base 基础路径
   * @returns 绝对路径
   */
  static resolve(p: string, base?: string): string {
    try {
      if (base) {
        return PathUtil.normalize(path.resolve(base, p));
      }
      return PathUtil.normalize(path.resolve(p));
    } catch (error) {
      console.error('解析绝对路径错误:', error);
      return '';
    }
  }

  /**
   * 判断路径是否以指定的前缀路径开头
   * @param p 需要检查的路径
   * @param prefix 前缀路径
   * @returns 是否以指定前缀开头
   */
  static startsWith(p: string, prefix: string): boolean {
    try {
      // 标准化两个路径
      const normalizedPath = PathUtil.normalize(p);
      const normalizedPrefix = PathUtil.normalize(prefix);

      // 确保前缀末尾有斜杠，以防止部分匹配
      // 例如: "/app" 不应该匹配 "/app-data"
      const prefixWithSlash = normalizedPrefix.endsWith('/')
        ? normalizedPrefix
        : normalizedPrefix + '/';

      // 特殊情况处理
      if (normalizedPrefix === '') {
        return true; // 空前缀始终匹配任何路径
      }

      if (normalizedPrefix === '/') {
        return normalizedPath.startsWith('/');
      }

      // 直接检查完全匹配的情况
      if (normalizedPath === normalizedPrefix) {
        return true;
      }

      // 检查是否以前缀开头，并确保前缀后是完整的路径段
      return normalizedPath.startsWith(prefixWithSlash) ||
        normalizedPath.startsWith(normalizedPrefix + '/');
    } catch (error) {
      console.error('检查路径前缀错误:', error);
      return false;
    }
  }

  /**
   * 获取路径的扩展名
   * @param p 路径
   * @returns 扩展名
   */
  static extname(p: string): string {
    try {
      return path.extname(p);
    } catch (error) {
      console.error('获取扩展名错误:', error);
      return '';
    }
  }

  /**
   * 从路径中去除指定的前缀
   * @param p 需要处理的路径
   * @param prefix 要去除的前缀
   * @returns 去除前缀后的路径，如果路径不以前缀开头则返回原路径
   */
  static removePrefix(p: string, prefix: string): string {
    try {
      // 检查路径是否以前缀开头
      if (!PathUtil.startsWith(p, prefix)) {
        return p; // 如果不是以前缀开头，直接返回原路径
      }

      // 标准化路径
      const normalizedPath = PathUtil.normalize(p);
      const normalizedPrefix = PathUtil.normalize(prefix);

      // 如果路径和前缀完全相同
      if (normalizedPath === normalizedPrefix) {
        return '/'; // 返回根路径
      }

      // 确保前缀末尾有斜杠
      const prefixWithSlash = normalizedPrefix.endsWith('/')
        ? normalizedPrefix
        : normalizedPrefix + '/';

      // 如果路径以带斜杠的前缀开头
      if (normalizedPath.startsWith(prefixWithSlash)) {
        return normalizedPath.substring(prefixWithSlash.length);
      }

      // 处理其他情况
      return normalizedPath.substring(normalizedPrefix.length);
    } catch (error) {
      console.error('移除路径前缀错误:', error);
      return p;
    }
  }
}
